package com.jxb.test;

/**
 * 1：先以固定频率往令牌桶中放令牌，桶放满了就拒绝
 * 2：模拟高并发场景，有大量请求过来
 * 3：限流判断：是否获取到令牌，获取到放行，获取不到进行限流
 */
public class TokenBucket {

    private static Long tokens = 0L;//现有令牌的数量
    private static Long capacity = 50L;//桶的阈值
    private static Long rate = 5L;//频率

    public static void main(String[] args) throws InterruptedException {
        //进行缓冲,将令牌放入桶中
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (;;) {
                    putTokens();
                }
            }
        }).start();
        //缓冲10s
        Thread.sleep(10000);
        System.out.println("预热完成，请求进入.....");
        new Thread(new Runnable() {
            @Override
            public void run() {
                //模拟高并发场景
                while (true) {
                    //模拟每5s一个请求进来不会触发限流
                    //模拟每2s一个请求进来会触发限流
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (!limit()) {
                        System.out.println("限流了");
                    }
                }
            }
        }).start();

    }

    public static boolean putTokens() {
        //判断是否到达阈值
        if (tokens > capacity) {
            return false;
        }
        //以固定频率放入桶
        try {
            tokens += 1;
            Thread.sleep(rate*1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return true;

    }

    public static boolean limit() {
        //判断是否能获取令牌
        if (tokens - 1 >= 0) {
            tokens -= 1;
            return true;
        }else {
            return false;
        }
    }

}
